package han.chensing.latos.maker.windows.dialog.sample;

import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ArraySelection;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import han.Chensing.CibMidi.MidiBasicInfo;
import han.Chensing.CibMidi.MidiFile;
import han.Chensing.CibMidi.MidiTrack;
import han.Chensing.CibMidi.raw.MidiEvent;
import han.chensing.latos.common.level.sample.Sample;
import han.chensing.latos.common.level.sample.SampleSet;
import han.chensing.latos.maker.res.Res;
import han.chensing.latos.maker.V;
import han.chensing.latos.maker.windows.dialog.base.BaseDialog;
import han.chensing.latos.maker.windows.widget.CUIList;
import han.chensing.latos.maker.windows.widget.CScrollList;
import han.chensing.latos.maker.windows.widget.MidiSelectorWidget;

public class SampleImportFromMidiDialog extends BaseDialog {
    MidiSelectorWidget selector;
    MidiFile midiFile;
    CScrollList<MidiTrack> tracksList;
    CScrollList<Sample> oriSamplesList;
    //CScrollList<Sample> tempSamplesList;
    CScrollList<Sample> choseSamplesList;
    TextButton closeButton;
    TextButton copyTempToChoseButton;
    Slider progressSlider;
    Slider offsetSlider;

    ArrayList<TrackSet> trackSets;
    ArrayList<Sample> selectedSamplesList;

    public SampleImportFromMidiDialog(File file){
        super("Import samples from midi");
        trackSets=new ArrayList<>();
        selectedSamplesList=new ArrayList<>();
        Skin skin = Res.get().get("skinBasic", Skin.class);
        setSize(1200,650);

        closeButton=new TextButton("Done",skin);
        closeButton.setBounds(getWidth()/2f-closeButton.getWidth()/2f,
                closeButton.getHeight()/2f,75,30);
        addActor(closeButton);

        tracksList=new CScrollList<>(skin,t->t.getNum()+"");
        tracksList.setBounds(10,95,150,525);
        addActor(tracksList);

        oriSamplesList= new CScrollList<>(skin, Sample::toString);
        oriSamplesList.setBounds(170,95,330,330);
        oriSamplesList.getCList().setMultiSelective(true);
        addActor(oriSamplesList);

        /*tempSamplesList=new CScrollList<>(skin, Sample::toString);
        tempSamplesList.setBounds(510,95,330,330);
        addActor(tempSamplesList);*/

        choseSamplesList=new CScrollList<>(skin,Sample::toString);
        choseSamplesList.setBounds(850,95,330,330);
        choseSamplesList.getCList().setMultiSelective(true);
        addActor(choseSamplesList);

        copyTempToChoseButton=new TextButton("Choose temp",skin);
        copyTempToChoseButton.setBounds(510,55,150,30);
        addActor(copyTempToChoseButton);

        progressSlider=new Slider(0f,100f,0.01f,false,skin);
        progressSlider.setBounds(170,430,1010,20);
        addActor(progressSlider);

        offsetSlider=new Slider(0,100f,0.01f,false,skin);
        offsetSlider.setBounds(170,400,1010,20);
        //addActor(offsetSlider);

        selector=new MidiSelectorWidget();
        selector.setBounds(170,450,1010,170);
        addActor(selector);

        try {
            analyzeMidi(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        updateMidiTracksList();
        updateTrackSets();

        closeButton.addListener(new ClickListener(){
            @Override
            public void clicked(InputEvent event, float x, float y) {
                super.clicked(event, x, y);
                List<SampleSet> sampleSets = V.project.getSampleData().getSampleSets();
                int midiNum=0;
                for (TrackSet trackSet : trackSets) {
                    if (trackSet.samples.isEmpty())
                        continue;
                    SampleSet sampleSet=new SampleSet();
                    sampleSet.setName("Midi - "+midiNum++);
                    sampleSet.getSamples().addAll(trackSet.samples);
                    sampleSets.add(sampleSet);
                }
                SampleImportFromMidiDialog.this.remove();
            }
        });
        copyTempToChoseButton.addListener(new ClickListener(){
            @Override
            public void clicked(InputEvent event, float x, float y) {
                super.clicked(event, x, y);
                int selectedIndex = tracksList.getCList().getSelectedIndex();
                TrackSet trackSet = trackSets.get(selectedIndex);
                if (trackSet==null)
                    return;
                List<Sample> items = selectedSamplesList;
                trackSet.samples.addAll(items);
                choseSamplesList.setData(trackSet.samples);
                updateChoseSamplesList();
            }
        });
        tracksList.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                int selectedIndex = tracksList.getCList().getSelectedIndex();
                TrackSet trackSet = trackSets.get(selectedIndex);
                selector.updateMidiTrack(trackSet);
                oriSamplesList.setData(trackSet.oriSamples);
                updateOriSamplesList();
                updateChoseSamplesList();
            }
        });
        oriSamplesList.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                selectedSamplesList.clear();
                ArraySelection<CUIList.CUIListItem<Sample>> selection = oriSamplesList.getCList().getSelection();
                for (CUIList.CUIListItem<Sample> sampleCUIListItem : selection)
                    selectedSamplesList.add(sampleCUIListItem.getValue());
            }
        });

        progressSlider.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                float value = progressSlider.getValue();
                selector.updateFlow(value);
            }
        });
        offsetSlider.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {

            }
        });

        moveToCenter();
    }

    private void updateOriSamplesList(){
        oriSamplesList.update();
        /*int selectedIndex = tracksList.getSelectedIndex();
        TrackSet trackSet = trackSets.get(selectedIndex);
        if (trackSet==null)
            return;
        UIListUtil.updateList(oriSamplesList,oriSamplesListScrollPane, trackSet.oriSamples);*/
    }

    private void updateChoseSamplesList(){
        choseSamplesList.update();
        /*int selectedIndex = tracksList.getSelectedIndex();
        TrackSet trackSet = trackSets.get(selectedIndex);
        if (trackSet==null)
            return;
        UIListUtil.updateList(choseSamplesList,choseSamplesListScrollPane, trackSet.samples);*/
    }

    public void updateTempSamplesList(ArrayList<Sample> samples){
        selectedSamplesList.clear();
        selectedSamplesList.addAll(samples);
        ArraySelection<CUIList.CUIListItem<Sample>> selection = oriSamplesList.getCList().getSelection();
        selection.clear();
        List<CUIList.CUIListItem<Sample>> dataList = oriSamplesList.getCList().getDataList();
        int i=0;
        for (CUIList.CUIListItem<Sample> sampleCUIListItem : dataList) {
            if (i>= samples.size())
                break;
            Sample sample = samples.get(i);
            Sample value = sampleCUIListItem.getValue();
            if (!sample.equals(value))
                continue;
            selection.add(sampleCUIListItem);
            i++;
        }
        selection.validate();
        oriSamplesList.invalidateHierarchy();
    }

    private void updateTrackSets(){
        trackSets.clear();
        List<MidiTrack> tracks = midiFile.getData().getTracks();
        for (MidiTrack track : tracks) {
            trackSets.add(new TrackSet(track));
        }
    }

    private void analyzeMidi(File file) throws IOException {
        midiFile=new MidiFile(file);
        midiFile.analyze();
    }

    private void updateMidiTracksList(){
        tracksList.setData(midiFile.getData().getTracks());
        tracksList.update();
        /*MidiData data = midiFile.getData();
        List<MidiTrack> tracks = data.getTracks();
        tracksList.clearItems();
        for(MidiTrack track:tracks)
            tracksList.getItems().add(track.getNum()+" "+track.getEvents().size());
        tracksList.invalidateHierarchy();*/
    }

    public class TrackSet{
        public List<Sample> oriSamples;
        public List<Sample> samples;
        public float totalTime;
        TrackSet(MidiTrack track){
            this.oriSamples=new ArrayList<>();
            this.samples=new ArrayList<>();
            List<MidiEvent> events = track.getEvents();
            MidiBasicInfo midiBasicInfo = midiFile.getData().getMidiBasicInfo();
            float millisecond = midiBasicInfo.microsecondPerQuarterNote / 1000f;
            float nowTime=0;
            for(MidiEvent event:events){
                float deltaTime = event.getDeltaTime() * millisecond / midiFile.getDataRaw().getBaseTime();
                nowTime+=deltaTime;
                if (deltaTime==0)
                    continue;
                if (event.getEventType()!= MidiEvent.EventType.KeyDown)
                    continue;
                Sample sample=new Sample();
                sample.setName("");
                sample.setTime(nowTime);
                oriSamples.add(sample);
            }
            totalTime=nowTime;
        }
    }
}
